package cn.zyjblogs.config.security;

import cn.zyjblogs.starter.common.entity.constant.CommonRedisKeyConstant;
import cn.zyjblogs.starter.common.entity.context.BaseContext;
import cn.zyjblogs.starter.redis.utils.RedisTemplateHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.DefaultCsrfToken;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Component
@RequiredArgsConstructor
public class OauthCsrfTokenRepository implements CsrfTokenRepository {
    static final String DEFAULT_CSRF_COOKIE_NAME = "XSRF-TOKEN";
    static final String DEFAULT_CSRF_PARAMETER_NAME = "_csrf";
    static final String DEFAULT_CSRF_HEADER_NAME = "X-XSRF-TOKEN";
    private String parameterName = "_csrf";
    private String headerName = "X-XSRF-TOKEN";

    private final RedisTemplateHandler<String, String> redisTemplateHandler;

    @Override
    public CsrfToken generateToken(HttpServletRequest httpServletRequest) {
        return new DefaultCsrfToken(this.headerName, this.parameterName, this.createNewToken());
    }

    @Override
    public void saveToken(CsrfToken csrfToken, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        String tokenValue = csrfToken == null ? "" : csrfToken.getToken();
        String key = CommonRedisKeyConstant.XSRF_TOKEN + BaseContext.getUsername();
        redisTemplateHandler.set(key, tokenValue);
        redisTemplateHandler.expire(key, 30, TimeUnit.DAYS);
        httpServletResponse.setHeader(headerName, tokenValue);
    }

    @Override
    public CsrfToken loadToken(HttpServletRequest httpServletRequest) {
        String tokenValue = redisTemplateHandler.get(CommonRedisKeyConstant.XSRF_TOKEN + BaseContext.getUsername());
        if (tokenValue == null) {
            return null;
        }
        return new DefaultCsrfToken(this.headerName, this.parameterName, tokenValue);
    }

    private String createNewToken() {
        return UUID.randomUUID().toString();
    }
}
